#ifndef SINGLETON_H
#define SINGLETON_H

#include <QtGlobal>
#include <QScopedPointer>

#include "callonce.h"
#include "../global/xnamespace.h"

X_BEGIN_NAMESPACE

/**
 * 线程安全的单例模板。
 *
 * http://wiki.qt.io/Qt_thread-safe_singleton
 */
template <class T>
class Singleton
{
private:
    typedef T* (*CreateInstanceFunction)();

public:
    static T* instance(CreateInstanceFunction create);

private:
    static void init();

    Singleton();
    ~Singleton();

    Q_DISABLE_COPY(Singleton)

    static QBasicAtomicPointer<void> create;
    static QBasicAtomicInt flag;
    static QBasicAtomicPointer<void> tptr;

    bool inited;
};

template <class T>
T* Singleton<T>::instance(CreateInstanceFunction create)
{
    Singleton::create.store((void*)create);
    qCallOnce(init, flag);
    return (T*)tptr.load();
}

template <class T>
void Singleton<T>::init()
{
    static Singleton singleton;
    if (singleton.inited) {
        CreateInstanceFunction createFunction = (CreateInstanceFunction)(Singleton::create.load());
        tptr.store(createFunction());
    }
}

template <class T>
Singleton<T>::Singleton() {
    inited = true;
}

template <class T>
Singleton<T>::~Singleton() {
    T* createdTptr = (T*)tptr.fetchAndStoreOrdered(nullptr);
    if (createdTptr) {
        // TODO: 需要区分单件是否被注册到QML，如果注册到QML中，则不能再次释放。
        // 单件已经由QML引擎接管
        //delete createdTptr;
    }
    create.store(nullptr);
}

template<class T> QBasicAtomicPointer<void> Singleton<T>::create = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
template<class T> QBasicAtomicInt Singleton<T>::flag = Q_BASIC_ATOMIC_INITIALIZER(CallOnce::CO_Request);
template<class T> QBasicAtomicPointer<void> Singleton<T>::tptr = Q_BASIC_ATOMIC_INITIALIZER(nullptr);

X_END_NAMESPACE

#endif // SINGLETON_H
